package com.cskaoyan.wordmemorize.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cskaoyan.wordmemorize.converter.TopicConverter;
import com.cskaoyan.wordmemorize.converter.VocConverter;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.*;
import com.cskaoyan.wordmemorize.excel.FillExcelData;
import com.cskaoyan.wordmemorize.excel.SingleExcelData;
import com.cskaoyan.wordmemorize.dao.entity.SingleTopic;
import com.cskaoyan.wordmemorize.listener.FillExcelDataListener;
import com.cskaoyan.wordmemorize.listener.FillExcelValidListener;
import com.cskaoyan.wordmemorize.listener.SingleExcelDataListener;
import com.cskaoyan.wordmemorize.listener.SingleExcelValidListener;
import com.cskaoyan.wordmemorize.request.ReviewSubTopicCommand;
import com.cskaoyan.wordmemorize.request.TopicCommand;
import com.cskaoyan.wordmemorize.request.TopicOptionCommand;
import com.cskaoyan.wordmemorize.request.VocPageRequest;
import com.cskaoyan.wordmemorize.service.TopicService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Service
public class TopicServiceImpl implements TopicService {

    @Autowired
    ReviewTopicMapper reviewTopicMapper;
    @Autowired
    TopicOptionsMapper topicOptionsMapper;
    @Autowired
    ReviewTopicOptionMapper reviewTopicOptionMapper;
    @Autowired
    TopicConverter topicConverter;
    @Autowired
    ReviewSubTopicMapper reviewSubTopicMapper;
    @Autowired
    VocMapper  vocMapper;
    @Autowired
    VocConverter vocConverter;

    @Override
    public VocDTO checkWord(String word) {
        QueryWrapper<VocDO> vocDOQueryWrapper = new QueryWrapper<>();
        vocDOQueryWrapper.eq("content", word);
        VocDO vocDO = vocMapper.selectOne(vocDOQueryWrapper);
        return vocConverter.vocDO2DTO(vocDO);
    }

    @Override
    public PageDTO<ReviewTopicDTO> getSingleChoicePage(VocPageRequest vocPageRequest) {
        //condition
        String bookId = vocPageRequest.getBookId();
        String chapterId = vocPageRequest.getChapterId();
        Integer topicType = vocPageRequest.getTopicType();
        String keyword = vocPageRequest.getKeyword();
        String categoryId = vocPageRequest.getCategoryId();
        Integer pageNum = vocPageRequest.getPageNum();
        Integer count = vocPageRequest.getCount();

        List<SingleTopic> singleTopicDOS = reviewTopicMapper.selectSingleTopicList(categoryId, bookId,
                chapterId, keyword,(pageNum-1)*count, count);

        List<ReviewTopicDO> reviewTopicDOS = new ArrayList<>();
        for (SingleTopic singleTopicDO : singleTopicDOS) {

            String id = singleTopicDO.getId();
            //根据topicId查询
            QueryWrapper<ReviewTopicDO> reviewTopicDOQueryWrapper = new QueryWrapper<>();
            reviewTopicDOQueryWrapper.eq("id", id);
            ReviewTopicDO reviewTopicDO = reviewTopicMapper.selectOne(reviewTopicDOQueryWrapper);
            reviewTopicDOS.add(reviewTopicDO);
        }
        long totalCount = reviewTopicMapper.selectSingleTotal(categoryId, bookId, chapterId,keyword);
        return topicConverter.topicDOPage2PageDTO(reviewTopicDOS, totalCount);
    }


    //GET /admin/topic/fillWord/list?categoryId=1853706302759071746
    // &bookId=1854094374856228865&chapterId=1927239385640902658&keyword=&pageNum=1
    // &count=10&topicType=2 HTTP/1.1
    @Override
    public PageDTO<ReviewTopicDTO> getFillWordPage(VocPageRequest vocPageRequest) {
        String bookId = vocPageRequest.getBookId();
        String chapterId = vocPageRequest.getChapterId();
        Integer topicType = vocPageRequest.getTopicType();
        String keyword = vocPageRequest.getKeyword();
        String categoryId = vocPageRequest.getCategoryId();
        Integer pageNum = vocPageRequest.getPageNum();
        Integer count = vocPageRequest.getCount();

        List<Long> ids = reviewTopicMapper.selectFillWordList(categoryId, bookId,
                chapterId, keyword,(pageNum-1)*count, count);
        List<ReviewTopicDO> reviewTopicDOS = new ArrayList<>();
        for (Long id : ids) {
            //根据topicId查询
            QueryWrapper<ReviewTopicDO> reviewTopicDOQueryWrapper = new QueryWrapper<>();
            reviewTopicDOQueryWrapper.eq("id", id);
            ReviewTopicDO reviewTopicDO = reviewTopicMapper.selectOne(reviewTopicDOQueryWrapper);
            reviewTopicDOS.add(reviewTopicDO);
        }
        long totalCount = reviewTopicMapper.selectFillWordTotal(categoryId, bookId, chapterId,keyword);
        return topicConverter.topicDOPage2PageDTO(reviewTopicDOS, totalCount);
    }

    @Override
    public void addTopic(TopicCommand command) {
        System.out.println(command);
        //插入题目
        ReviewTopicDO reviewTopicDO = topicConverter.command2TopicDO(command);
        String vocabulary = command.getVocabulary();
        //System.out.println(vocabulary);
        QueryWrapper<VocDO> vocDOQueryWrapper = new QueryWrapper<>();
        vocDOQueryWrapper.eq("content", vocabulary)
                .select("id");
        if(reviewTopicDO.getTopicType()==1) {
            VocDO vocDO = vocMapper.selectOne(vocDOQueryWrapper);
            reviewTopicDO.setVocId(vocDO.getId());
        }
        if(reviewTopicDO.getTopicType()==2) {
            StringBuilder topic = new StringBuilder();
            for (ReviewSubTopicCommand subTopic:command.getSubTopics()) {
                topic.append(subTopic.getTopicItem()).append("\n");
            }
            reviewTopicDO.setTopic(topic.toString());
        }
        reviewTopicMapper.insert(reviewTopicDO);
        if(reviewTopicDO.getTopicType()==2) {
            //插入子题目
            List<ReviewSubTopicDO> reviewSubTopicDOs = topicConverter.commands2ReviewSubTopicDOs(command.getSubTopics());
            for (ReviewSubTopicDO reviewSubTopicDO : reviewSubTopicDOs) {
                reviewSubTopicDO.setTid(reviewTopicDO.getId());
                vocDOQueryWrapper.clear();
                vocDOQueryWrapper.eq("content",reviewSubTopicDO.getVocabulary());
                VocDO vocDO = vocMapper.selectOne(vocDOQueryWrapper);
                reviewSubTopicDO.setVocId(vocDO.getId());
                reviewSubTopicMapper.insert(reviewSubTopicDO);
            }
        }
        //插入选项
        List<TopicOptionCommand> options = command.getOptions();

        for (TopicOptionCommand topOptionCommand:options) {
            TopicOptionDO topicOptionDO = topicConverter.reviewSubTopicCommand2TopicDO(topOptionCommand);
            topicOptionDO.setTid(reviewTopicDO.getId());
            if(topicOptionDO.getItem().equals(vocabulary))
            {
                topicOptionDO.setIsAnswer(1);
                System.out.println("getItem"+topicOptionDO.getItem());
            }
            topicOptionsMapper.insert(topicOptionDO);
        }


    }

    @Override
    public ReviewTopicDTO getTopic(@RequestBody Long topicId) {
        QueryWrapper<ReviewTopicDO> reviewTopicDOQueryWrapper = new QueryWrapper<>();
        reviewTopicDOQueryWrapper.eq("id", topicId);
        ReviewTopicDO reviewTopicDO = reviewTopicMapper.selectOne(reviewTopicDOQueryWrapper);
        ReviewTopicDTO reviewTopicDTO = topicConverter.reviewTopicDO2DTO(reviewTopicDO);
        //查询子题目
        if(reviewTopicDTO.getTopicType()==2) {
//            System.out.println(topicId);
            QueryWrapper<ReviewSubTopicDO> reviewSubTopicDOQueryWrapper = new QueryWrapper<>();
            reviewSubTopicDOQueryWrapper.eq("tid", topicId);
            List<ReviewSubTopicDO> reviewSubTopicDOS = reviewSubTopicMapper.selectList(reviewSubTopicDOQueryWrapper);
            List<ReviewSubTopicDTO> reviewSubTopicDTOS = topicConverter.reviewSubTopicDOs2DTOs(reviewSubTopicDOS);
            reviewTopicDTO.setSubTopics(reviewSubTopicDTOS);
        }
        //查询选项
        QueryWrapper<TopicOptionDO> topicOptionDOQueryWrapper = new QueryWrapper<>();
        topicOptionDOQueryWrapper.eq("tid", topicId);
        List<TopicOptionDO> topicOptionDOs = topicOptionsMapper.selectList(topicOptionDOQueryWrapper);
        List<TopicOptionDTO> topicOptionDTOS = topicConverter.topicOptionDOs2DTOs(topicOptionDOs);
        reviewTopicDTO.setOptions(topicOptionDTOS);

        //返回 ReviewTopicDTO
        return reviewTopicDTO;
    }

    @Override
    public void updateTopic(TopicCommand command) {
        //修改review_topic表
            //修改单词id
        ReviewTopicDO reviewTopicDO = topicConverter.command2TopicDO(command);
        if(reviewTopicDO.getTopicType()==1) {
            QueryWrapper<VocDO> vocDOQueryWrapper = new QueryWrapper<>();
            vocDOQueryWrapper.eq("content", command.getVocabulary());
            VocDO vocDO = vocMapper.selectOne(vocDOQueryWrapper);
            reviewTopicDO.setVocId(vocDO.getId());
        }
        //
        UpdateWrapper<ReviewTopicDO> reviewTopicDOUpdateWrapper = new UpdateWrapper<>();
        reviewTopicDOUpdateWrapper.eq("id", reviewTopicDO.getId());
        reviewTopicMapper.update(reviewTopicDO, reviewTopicDOUpdateWrapper);
        //修改review_sub_topic表
        if(reviewTopicDO.getTopicType()==2) {
            List<ReviewSubTopicDO> reviewSubTopicDOS = topicConverter.commands2ReviewSubTopicDOs(command.getSubTopics());
            UpdateWrapper<ReviewSubTopicDO> reviewSubTopicDOUpdateWrapper = new UpdateWrapper<>();
            for (ReviewSubTopicDO reviewSubTopicDO : reviewSubTopicDOS) {
                //获取voc_Id
                QueryWrapper<VocDO> vocDOQueryWrapper = new QueryWrapper<>();
                vocDOQueryWrapper.eq("content", reviewSubTopicDO.getVocabulary());
                VocDO vocDO = vocMapper.selectOne(vocDOQueryWrapper);
                reviewSubTopicDO.setVocId(vocDO.getId());

                //子题目正常更新
                if(reviewSubTopicDO.getId()==null) {
                    //新增子题目
                    reviewSubTopicMapper.insert(reviewSubTopicDO);
                    continue;
                }
                reviewSubTopicDOUpdateWrapper.eq("id", reviewSubTopicDO.getId());
                reviewSubTopicMapper.update(reviewSubTopicDO, reviewSubTopicDOUpdateWrapper);
                reviewSubTopicDOUpdateWrapper.clear();
            }
        }
        //修改topic_options表
        List<TopicOptionCommand> options = command.getOptions();
        UpdateWrapper<TopicOptionDO> topicOptionDOUpdateWrapper = new UpdateWrapper<>();
        String vocabulary = reviewTopicDO.getVocabulary();
        for (TopicOptionCommand topOptionCommand:options) {
            //增加选项
            TopicOptionDO topicOptionDO = topicConverter.reviewSubTopicCommand2TopicDO(topOptionCommand);
            if(topicOptionDO.getItem().equals(vocabulary)) topicOptionDO.setIsAnswer(1);
            else topicOptionDO.setIsAnswer(0);
            if(topicOptionDO.getId()==null) {
                if(reviewTopicDO.getTopicType()==1) {
                    topicOptionDO.setTid(reviewTopicDO.getId());
                    topicOptionsMapper.insert(topicOptionDO);
                    continue;
                }
                else if(reviewTopicDO.getTopicType()==2) {
                    //更新子题目中，如果修改了干扰性，需要把option表中干扰项先删除，再新增新的干扰项
                    //删除干扰项
                    Long id = reviewTopicDO.getId();
                    QueryWrapper<TopicOptionDO> topicOptionDOQueryWrapper = new QueryWrapper<>();
                    topicOptionDOQueryWrapper.eq("tid", id);
                    topicOptionsMapper.delete(topicOptionDOUpdateWrapper);
                    //新增干扰项
                    topicOptionDO.setTid(id);
                    topicOptionsMapper.insert(topicOptionDO);
                }
            }
            topicOptionDOUpdateWrapper.eq("id", topicOptionDO.getId());
            topicOptionsMapper.update(topicOptionDO,topicOptionDOUpdateWrapper);
        }
    }

    @Override
    public DeleteTopicOperateDTO deleteTopic(Long topicId, Integer topicType) {
        //删除review_topic表
        QueryWrapper<ReviewTopicDO> reviewTopicDOQueryWrapper = new QueryWrapper<>();
        reviewTopicDOQueryWrapper.eq("id", topicId);
        ReviewTopicDO reviewTopicDO = reviewTopicMapper.selectOne(reviewTopicDOQueryWrapper);
        reviewTopicMapper.delete(reviewTopicDOQueryWrapper);
        //根据tid删除review_sub_topic表
        if(topicType==2) {
            QueryWrapper<ReviewSubTopicDO> reviewSubTopicDOQueryWrapper = new QueryWrapper<>();
            reviewSubTopicDOQueryWrapper.eq("tid", topicId);
            reviewSubTopicMapper.delete(reviewSubTopicDOQueryWrapper);
        }
        //根据tid删除topic_options表
        QueryWrapper<TopicOptionDO> topicOptionDOQueryWrapper = new QueryWrapper<>();
        topicOptionDOQueryWrapper.eq("tid", topicId);
        topicOptionsMapper.delete(topicOptionDOQueryWrapper);
        return topicConverter.topicDO2DeleteTopicDTO(reviewTopicDO);
    }

    @Override
    public void topicExcelValidate(String type, MultipartFile file) throws IOException {
        if(type.equals("single")) {
//            - Excel文件头的是否与模版文件的文件头数量，内容是否相同(不强制要求)
//                    - 校验单元格中是否有空数据(是否有对象的属性值为null)
//                    - 校验单选题所针对的单词是否在voc表中存在
//                    - 校验单选题的正确答案下标值是否合法(比如必须是数值，必须在[1, 4]范围)
            SingleExcelValidListener singleExcelValidListener = new SingleExcelValidListener(vocMapper);
            EasyExcel.read(file.getInputStream(), SingleExcelData.class, singleExcelValidListener)
                    // 指定读取的sheet我们的一个excel只使用默认的一个sheet所以不用指定
                    .sheet()
                    // 开始读取,方法执行完毕，那么整个Excel文件也读取完了
                    .doRead();
        }
        else if(type.equals("fill")) {
            FillExcelValidListener fillExcelValidListener = new FillExcelValidListener(vocMapper);
            EasyExcel.read(file.getInputStream(), FillExcelData.class, fillExcelValidListener)
                    // 指定读取的sheet我们的一个excel只使用默认的一个sheet所以不用指定
                    .sheet()
                    // 开始读取,方法执行完毕，那么整个Excel文件也读取完了
                    .doRead();

        }

    }

    @Override
    public ExcelAddOperateDTO addSingleChoiceExcel(MultipartFile file, Long employeeId) throws IOException {
        SingleExcelDataListener singleExcelDataListener = new SingleExcelDataListener(reviewTopicMapper, topicOptionsMapper, vocMapper);
        EasyExcel.read(file.getInputStream(), SingleExcelData.class, singleExcelDataListener)
                // 指定读取的sheet我们的一个excel只使用默认的一个sheet所以不用指定
                .sheet()
                // 开始读取,方法执行完毕，那么整个Excel文件也读取完了
                .doRead();
        String name = file.getName();
        Integer lines = singleExcelDataListener.getLines();
        ExcelAddOperateDTO excelAddOperateDTO = new ExcelAddOperateDTO();
        excelAddOperateDTO.setFileName(name);
        excelAddOperateDTO.setTotalCount(lines);
        return excelAddOperateDTO;
    }

    @Override
    public ExcelAddOperateDTO addFillWordExcel(MultipartFile file, Long employeeId) throws IOException {
        FillExcelDataListener fillExcelDataListener = new FillExcelDataListener(vocMapper,reviewTopicMapper,reviewSubTopicMapper, topicOptionsMapper);
        EasyExcel.read(file.getInputStream(), FillExcelData.class, fillExcelDataListener)
                // 指定读取的sheet我们的一个excel只使用默认的一个sheet所以不用指定
                .sheet()
                // 开始读取,方法执行完毕，那么整个Excel文件也读取完了
                .doRead();
        String name = file.getName();
        Integer lines = fillExcelDataListener.getLines();
        ExcelAddOperateDTO excelAddOperateDTO = new ExcelAddOperateDTO();
        excelAddOperateDTO.setFileName(name);
        excelAddOperateDTO.setTotalCount(lines);
        return excelAddOperateDTO;
    }

    @Override
    public DeleteSubTopicOperateDTO deleteSubTopic(Long id) {
        //查询出删除的子题目的voc和topic
        QueryWrapper<ReviewSubTopicDO> reviewSubTopicDOQueryWrapper = new QueryWrapper<>();
        reviewSubTopicDOQueryWrapper.eq("id", id);
        ReviewSubTopicDO reviewSubTopicDO = reviewSubTopicMapper.selectOne(reviewSubTopicDOQueryWrapper);
        String vocabulary = reviewSubTopicDO.getVocabulary();
        String topicItem = reviewSubTopicDO.getTopicItem();
        Long tid = reviewSubTopicDO.getTid();
        //查询出子题目对应的题目
        QueryWrapper<ReviewTopicDO> reviewTopicDOQueryWrapper = new QueryWrapper<>();
        reviewTopicDOQueryWrapper.eq("id", tid);
        ReviewTopicDO reviewTopicDO = reviewTopicMapper.selectOne(reviewTopicDOQueryWrapper);
        String[] topics = reviewTopicDO.getTopic().split("\n");
        StringBuilder newTopic = new StringBuilder();
        for (String topic:topics) {
            if(topic.equals(topicItem)) continue;
            newTopic.append(topic).append("\n");
        }
        String[] vocS = reviewTopicDO.getVocabulary().split(",");
        StringBuilder newVoc = new StringBuilder();
        for (String voc:vocS) {
            if(voc.equals(vocabulary)) continue;
            newVoc.append(voc).append(",");
        }
        //修改review_topic中的vocabulary和topic
        UpdateWrapper<ReviewTopicDO> reviewTopicDOUpdateWrapper = new UpdateWrapper<>();
        reviewTopicDOUpdateWrapper.eq("id", reviewTopicDO.getId())
                .setSql("vocabulary = '"+newVoc+"',topic = '"+newTopic+"'");
        reviewTopicMapper.update(null, reviewTopicDOUpdateWrapper);
        //删除子题目
        reviewSubTopicDOQueryWrapper.clear();
        reviewSubTopicDOQueryWrapper.eq("id", id);
        reviewSubTopicMapper.delete(reviewSubTopicDOQueryWrapper);
        //修改sub_topic_num
        Integer subTopicNumber = reviewSubTopicDO.getSubTopicNumber();
        UpdateWrapper<ReviewSubTopicDO> reviewSubTopicDOUpdateWrapper = new UpdateWrapper<>();
        reviewSubTopicDOUpdateWrapper.eq("tid", tid)
                .gt("sub_topic_number", subTopicNumber)
                .setSql("sub_topic_number = sub_topic_number - 1");
        reviewSubTopicMapper.update(null, reviewSubTopicDOUpdateWrapper);
        return topicConverter.toDeleteSubTopicDTO(reviewSubTopicDO);
    }

    @Override
    public DeleteTopicOptionOperateDTO deleteTopicOption(Long id) {
        //删除选项
        TopicOptionDO topicOptionDO = topicOptionsMapper.selectById(id);
        QueryWrapper<TopicOptionDO> topicOptionDOQueryWrapper = new QueryWrapper<>();
        topicOptionDOQueryWrapper.eq("id", id);
        topicOptionsMapper.delete(topicOptionDOQueryWrapper);
        Long tid = topicOptionDO.getTid();
        QueryWrapper<ReviewTopicDO> reviewTopicDOQueryWrapper = new QueryWrapper<>();
        reviewTopicDOQueryWrapper.eq("id", tid);
        ReviewTopicDO reviewTopicDO = reviewTopicMapper.selectOne(reviewTopicDOQueryWrapper);
        //对于单项选择，修改表中的optionNum
        if(reviewTopicDO.getTopicType()==1) {
            Integer optionNumber = topicOptionDO.getOptionNumber();
            UpdateWrapper<TopicOptionDO> topicOptionDOUpdateWrapper = new UpdateWrapper<>();
            topicOptionDOUpdateWrapper.eq("tid", tid)
                    .gt("option_number", optionNumber)
                    .setSql("option_number = option_number - 1");
            topicOptionsMapper.update(topicOptionDOUpdateWrapper);
        }
        return topicConverter.toDeleteTopicOptionDTO(topicOptionDO, reviewTopicDO.getTopic());
    }
}
